/*
 * Copyright (c) 2009 Marius Mathiesen <marius.mathiesen@gmail.com>
* 
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* 
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
 */
package no.trafikanten;

import java.util.ArrayList;
import java.util.Iterator;


//import javax.xml.parsers.SAXParser; 
//import javax.xml.parsers.SAXParserFactory; 
//import org.xml.sax.InputSource; 
//import org.xml.sax.XMLReader; 
import javax.xml.parsers.*;

import java.io.IOException;
import java.io.InputStream;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.*;
//import trafikanten.*;
public class Stop 
{
	public String stopName;
	private String title, subtitle;
	public int stopId, favoriteCount;
	private double easting, northing;
	
	public static ArrayList<Stop> fetchStationsFromInputStream(InputStream s) throws Exception
	{
		ArrayList<Stop> result = new ArrayList<Stop>();
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		
		
		Document document = builder.parse(s);
		NodeList stops = document.getElementsByTagName("StopMatch");
		for (int i = 0; i < stops.getLength(); i++)
		{
			Node st = stops.item(i);
			Stop currentStop = new Stop();
			NodeList children = st.getChildNodes();
			for (int n = 0; n < children.getLength(); n++)
			{
				Node currentChild = children.item(n);
				if (currentChild.getNodeName().equalsIgnoreCase("StopName"))
				{
					TextExtractor tx = new TextExtractor(currentChild);
					currentStop.setName(tx.extractStringValue());
				}
				else if (currentChild.getNodeName().equalsIgnoreCase("fromid"))
				{
					TextExtractor tx = new TextExtractor(currentChild);
					currentStop.setId(Integer.parseInt(tx.extractStringValue()));
				}
				else if (currentChild.getNodeName().equals("XCoordinate"))
				{
					TextExtractor tx = new TextExtractor(currentChild);
					currentStop.setEasting(Integer.parseInt(tx.extractStringValue()));
				}
				else if (currentChild.getNodeName().equals("YCoordinate"))
				{
					TextExtractor tx = new TextExtractor(currentChild);
					currentStop.setNorthing(Integer.parseInt(tx.extractStringValue()));
				}
			}
			result.add(currentStop);
		}
		return result;

	}
	
	public static ArrayList<Departure>getDeparturesFromInputStream(InputStream s) throws Exception
	{
		ArrayList<Departure> result = new ArrayList<Departure>();
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		
		Document document = builder.parse(s);
		NodeList departures = document.getElementsByTagName("DISDeviation");
		for (int i = 0; i < departures.getLength(); i++)
		{
			Node st = departures.item(i);
			Departure d = new Departure();
			NodeList children = st.getChildNodes();
			for (int n = 0; n < children.getLength(); n++)
			{
				Node currentChild = children.item(n);
				TextExtractor tx = new TextExtractor(currentChild);
				if (currentChild.getNodeName().equalsIgnoreCase("LineID"))
				{
					d.setLineNumber(tx.toString());
				}
				else if (currentChild.getNodeName().equalsIgnoreCase("DestinationStop"))
				{
					d.setDestinationName(tx.extractStringValue());
				}
				else if (currentChild.getNodeName().equalsIgnoreCase("DirectionID"))
				{
					d.setDirectionNumber(tx.toInt());
				}
				else if (currentChild.getNodeName().equalsIgnoreCase("ExpectedDISDepartureTime"))
				{
					d.setExpectedDeparture(tx.toDate());
				}
			}
			result.add(d);
		}
		return result;
	}
	
	public ArrayList<DepartureGroup>extractDepartureGroups(ArrayList<Departure>departures)
	{
		ArrayList<DepartureGroup> result = new ArrayList<DepartureGroup>();
		Iterator<Departure> it = departures.iterator();
		while(it.hasNext())
		{
			Departure d = (Departure) it.next();
			DepartureGroup _d = new DepartureGroup(d.getDepartureNumber(), d.getLineNumber(), d.getDestinationName());
			_d.setDirection(d.getDirection());
			DepartureGroup dg;
			if (result.contains(_d))
			{
				dg = result.get(result.indexOf(_d));
			}
			else
			{
				_d.setTransportationId(d.getTransportationType());
				_d.setTransportationName(d.getTransportationName());
				_d.setDirection(d.getDirection());
				
				result.add(_d);
				dg = _d;				
			}
			dg.addDepartures(d.getExpectedDeparture());
		}
		return result;
	}
	
	// Return realtime departures
	public ArrayList<DepartureGroup> getDepartures() throws Exception
	{
		String subwayUrl = "http://www.sis.trafikanten.no:8088/xmlrtpi/dis/request?DISID=SN$" + this.stopId;
		String busAndTramUrl = "http://www.sis.trafikanten.no/xmlrtpi/dis/request?DISID=SN$" + this.stopId;
		DeadSimpleHttpClient subwayClient = new DeadSimpleHttpClient(subwayUrl);
		InputStream subwayStream;
		try {
			subwayStream = subwayClient.getInputStream();
		} catch (IOException e) {
			return null;
		}
		
		DeadSimpleHttpClient busClient = new DeadSimpleHttpClient(busAndTramUrl);
		InputStream busStream;
		try {
			busStream = busClient.getInputStream();
		} catch (IOException e) {
			return null;
		}
		
		ArrayList<Departure> departures = getDeparturesFromInputStream(subwayStream);
		departures.addAll(getDeparturesFromInputStream(busStream));
		ArrayList<DepartureGroup> result = extractDepartureGroups(departures);
		return result;
	}
	

	
	public void setNorthing(int northing)
	{
		this.northing = (double) northing;
	}
	public void setEasting(int easting)
	{
		this.easting = (double) easting;
	}
	public double getEasting()
	{
		return this.easting;
	}
	public double getNorthing()
	{
		return this.northing;
	}
	public int getStopId()
	{
		return this.stopId;
	}
	public void setFavoriteCount(int count)
	{
		favoriteCount = count;
	}
	public void setStopId(int stopId)
	{
		this.stopId = stopId;
	}
	
	public static ArrayList<Stop> lookupByName(String searchTerm) throws Exception
	{
		String searchTermEncoded = java.net.URLEncoder.encode(searchTerm, "UTF-8");
		DeadSimpleHttpClient c = new DeadSimpleHttpClient("http://www5.trafikanten.no/txml/?type=1&stopname=" + searchTermEncoded);
		InputStream s = c.getInputStream();
		return fetchStationsFromInputStream(s);
	}
	
	public Stop()
	{
		
	}
	public String toString()
	{
		return this.stopName;
	}
	public void setName(String name)
	{
		this.stopName = name;
		if (name.indexOf("(") != -1)
		{
			int idx = name.indexOf("(");
			String title = name.substring(0, idx - 1);
			String subtitle = name.substring(idx +1 , name.length() - 1);
			this.title = title;
			this.subtitle = subtitle;
		}
		else
		{
			this.title = name;
		}
	}
	public String getTitle()
	{
		return this.title;
	}
	public String getSubtitle()
	{
		return this.subtitle;
	}
	public void setTitle(String title)
	{
		this.title = title;
	}
	public void setSubtitle(String subtitle)
	{
		this.subtitle = subtitle;
	}
	public void setId(int id)
	{
		this.stopId = id;
	}
	public Stop(String stopName, int stopId)
	{
		this.stopName = stopName;
		this.stopId = stopId;
	}
}
